返回首页
   
   知识点
   递归取数
   ;WITH ent
   AS (SELECT EntryID,0 AS _parentId
	 FROM #LevelOne
	 UNION ALL
	 SELECT a.EntryID,a._parentId
	 FROM #Result a
		  INNER JOIN ent b ON a._parentId=b.EntryID
	 )
	 SELECT DISTINCT EntryID INTO #TopToBottom FROM ent
     其实UNION ALL前的语句相当于初始化值,然后决定这些值是向上OR向下递归
	 
	 知识点
	 DECLARE @sql VARCHAR(1000)
	 SET @sql='SELECT
	 1234 AS Col1
	 4321 AS Col2'
	 PRINT @sql
	 EXEC (@sql)
	 动态别名只能用动态语句
	 
	 知识点
	 反转字符串
	 SELECT REVERSE('abc')
	 
	 高速
	 --查询死锁
	 select request_session_id 锁表进程,OBJECT_NAME(resource_associated_entity_id) 被锁表名
	 from sys.dm_tran_locks where resource_type='OBJECT'
	 --处理死锁
	 declare @spid int
	 Set @spid=60  --锁表进程
	 declare @sql varchar(1000)
	 set @sql='kill '+cast(@spid as varchar)
	 exec (@sql)
	 
	 知识点
	 Between..AND..
	 包括两边的边界值 可以为数值、文本、日期(注意是当天0点)
	 
	 知识点
	 使用Exists条件而不用inner join 或 其他join 是因为可能有多条匹配
	 包括两边的边界值 可以为数值、文本、日期(注意是当天0点)
	 
	 高速
	 游标样例
	
	 DECLARE @ProCode NVARCHAR(50);
			DECLARE @UserId NVARCHAR(50);
			DECLARE @Count INT;
			BEGIN  
                DECLARE Update_cursora CURSOR LOCAL  static read_only forward_only FOR
                    select ProductCodeId,UserCode from Product_User_Relation where DeleteFlag =0 and ProductCodeId like '9%' ---And UserCode='duanjin 06481'
                OPEN Update_cursora;
                FETCH NEXT FROM Update_cursora INTO @ProCode,@UserId
                WHILE @@FETCH_STATUS = 0
                    BEGIN
						select * into #temp from (
						select ProID,ProCode FROM dbo.ProductInfo where ParentCode=@ProCode --A
						--B
						union all
						select ProID,ProCode FROM ProductInfo where ParentCode in(
						select ProCode from dbo.ProductInfo where ParentCode=@ProCode
						)
						union all
						--C
						select ProID,ProCode FROM ProductInfo where ParentCode in(
						select ProCode from ProductInfo where ParentCode in(
						select ProCode from ProductInfo where ParentCode=@ProCode
						)
						)
						)pro
						where  not exists(select 1 from Product_User_Relation where UserCode=@UserId And pro.ProCode=ProductCodeId);
					   DROP TABLE #temp
					   FETCH NEXT FROM Update_cursora INTO @ProCode,@UserId
					END;
                CLOSE Update_cursora;
                DEALLOCATE Update_cursora;
            END;
		
		
		高速
		压缩日志 
 USE[PersonalInput]  
			 GO  
			 ALTER DATABASE PersonalInput SET RECOVERY SIMPLE WITH NO_WAIT  
			 GO  
			 ALTER DATABASE PersonalInput SET RECOVERY SIMPLE   --简单模式  
			 GO  
			 USE PersonalInput  
			 GO  
			 DBCC SHRINKFILE (N'PersonalInput_log' , 2, TRUNCATEONLY)  --设置压缩后的日志大小为2M,可以自行指定  
			 GO  
			 USE[PersonalInput]  -- 注意要把使用的数据库不是master 还原为完整模式
			 GO  
			 ALTER DATABASE PersonalInput SET RECOVERY FULL WITH NO_WAIT  
			 GO  
			 ALTER DATABASE PersonalInput SET RECOVERY FULL  --还原为完全模式  
			 GO 
 
	
	
高速
		更新统计信息 
--更新库所有表的统计信息
--EXEC sp_updatestats
go
--更新某一个表的统计信息
UPDATE STATISTICS Sales.SalesOrderDetail;
GO
--更新某一个索引的统计信息
UPDATE STATISTICS Sales.SalesOrderDetail AK_SalesOrderDetail_rowguid;
高速
		查询表字段 
select * from sys.columns where object_id=object_id('table_name') 
sys.columns - 保存当前数据库中所有表的所有字段
object_id('objectname') 返回对象的ID值
高速
		表更新相关 
--根据不同条件 把某列值更新为其他值 
UPDATE Table SET Column= 
CASE WHEN Column=Value 
THEN Value 
WHEN Column=Value 
THEN Value END 
--根据两个表关联条件 把其中一个表中字段数据更新到另一个表的字段中 
UPDATE TableA 
SET TableA.Column=B.Column 
FROM TableB B WHERE TableA.Column=B.Column 
-- 使用别名 
UPDATE ent 
SET EntryCName=bak.EntryCName, 
PriorityLevel=bak.PriorityLevel, 
Remark=bak.Remark, 
Description=bak.Description, 
Status=0, 
DeleteFlag=0 
FROM Sol_Entry bak 
INNER JOIN Sol_EntryRelation rel ON bak.EntryID=rel.BackEntryID 
INNER JOIN Sol_Entry ent ON ent.EntryID=rel.EntryID WHERE ent.BlID=4 
AND bak.Status=-2 
--update 和from 来自同一个表时 update后必须用别名 from 后用inner join 
UPDATE col 
SET col.Name=bak.Name, 
col.Description=bak.Description, 
col.Status=0 
FROM Sol_EntryColName bak 
INNER JOIN Sol_EntryColName col ON col.ColID=bak.BackColID 
WHERE bak.Status=-2 AND Sol_EntryColName.BlID=:BlID 
高速
表删除相关 
DELETE ent
FROM  TableA ent
INNER JOIN TableB rel ON ent.ID=rel.ID
WHERE rel.Type=1
知识点
查询表上依赖关系 
在表上右键 有个依赖关系 点击后能看到依赖的表,函数,存储过程,视图 如果某个字段更新了(字段大小改变等) 像视图之类的依赖关系必须更新 
额外注意存储过程中遇到拼接字符串的表名是查询不到依赖关系的,只有sql语句中可以查到
高速
创建存储过程 
-- ============================================= 
-- Author:	
-- Create date: 
-- Description:	获取产品工程类型数据及产品列 
-- ============================================= 
ALTER PROCEDURE [dbo].[P_GetProductCol] 
@blId INT, --基线id 
@userId NVARCHAR(100),
--用户工号 e.g ys2338 ,17333 @proAttr NVARCHAR(100),
--产品列内容 查询条件,传递的是字典表的ConsValue,e.g:UnSupport,Other 
@isEdit bit,--0:不是编辑 1是编辑 
@showType INT -- 类型 0:产品列名称显示 1:使用Pro_ 列ID (为前端处理方便) 
AS BEGIN 
DECLARE @procol	VARCHAR(max) --有权限的产品列 
DECLARE @sql	VARCHAR(max) 
--拼接的sql exec(@sql) 
--select @sql END; 
知识点
CHARINDEX的使用 
select charindex('a','abca') 
result :1
从左到右只返回第一个匹配到的节点,下标从1开始 该函数无法使用索引
小坑
left join 的使用 
一个主表main left join 业务表T1 如要保持主表完整性,筛选条件要跟在T1后,不能放到主表where 条件中,否则是筛选主表了  
高速
检查是否有临时表 
if object_id(N'tempdb..#K_Temp',N'U') is not null
begin 
 Table #K_Temp 
 print '删除成功' 
 end 
  
高速
查询表创建时间 
select distinct xtype from sysobjects 
-- select name,crdate from sysobjects where xtype = 'TF' --表值函数 
-- select name,crdate from sysobjects where xtype = 'FN' --标量值函数 
-- select name,crdate from sysobjects where xtype = 'P' --存储过程 
-- select name,crdate from sysobjects where xtype = 'U' --表 
-- select name,crdate from sysobjects where xtype = 'V' -- 视图  
知识点
行转列函数定义 
SELECT ,
[first pivoted column] AS ,
[second pivoted column] AS ,
…
[last pivoted column] AS
FROM
(<查询表或者子查询作为数据源>)
AS 表别名
PIVOT
(
<聚合函数>(<被聚合的列>)(原有的数据列)
FOR
[<待转换的列名称,此列的多个唯一值将被转换为列标题>(转换前列名)]
IN ( [first pivoted column], [second pivoted column],
… [last pivoted column])
) AS <旋转表的别名>
<可选的排序子句 order by >;
高速
行转列例子一则 
if object_id('tempdb..#test')  is not null
drop table #test
create table #test
( 事项名称 varchar(200),
  年月 varchar(7),
  受理数量 int ,
  办结数量 int
)
insert into #test 
select '注销','2019-01',77,77
union all 
select '注销','2019-02',66,77
union all 
select '延续','2019-03',16,16
union all 
select '注销','2019-04',16,16
union all 
select '延续','2019-04',120,115
 --select *from  #test
  declare  @event varchar(3000)='',@sql varchar(3000)='',@queryexp varchar(3000)=''
   if object_id('tempdb..#hbTab') is not null
     drop table #hbtab
  select   事项名称,(年月+'_受理') as [year],受理数量,年月 into #hbtab  from #test
   --列转行
  insert into #hbtab
  select  事项名称,(年月+'_办结') as [year],办结数量,年月 from #test
  --获取行的属性
  --select *from #hbtab
  select @event=@event+',['+[year]+']'  from (select distinct [year] from #hbtab) a order by [year]
  select @queryexp=@queryexp+',max(['+[year]+']) as '+'['+[year]+']'  from (select distinct [year] from #hbtab) a order by [year]
select  @queryexp=right(@queryexp,len(@queryexp)-1)
select  @event=right(@event,len(@event)-1)
--select *from #hbtab order by year
set @sql='select 事项名称,'+@queryexp+' from( select 事项名称,'+@event +'from #hbtab a  
pivot (max(受理数量) for year in('+@event+') 
) as pv ) b group by 事项名称'
print @sql
 exec(@sql)
原文:https://blog.csdn.net/u010892506/article/details/89458862
高速
逗号分隔的字符串转换为Table数据 
DECLARE @person VARCHAR(300)='liuyujing,liufeng,zhaiguoxiu' 
DECLARE @tmpsql NVARCHAR(4000) 
SELECT @tmpsql='SELECT ''' + REPLACE(@person,',',''' UNION ALL SELECT ''')+ '''' 
PRINT @tmpsql 
exec sp_executesql @tmpsql 
坑
临时表或表无索引时 插入有序数据(按字符串列排序) 在临时表或表中是无序的 
1.可以创建索引解决 Create Clustered Index IDX_Table_Name ON Table(name)
2.可以引入新的排序后的序号列解决 select ROW_NUMBER() over(order by oi.CreatedOn desc) as row_num,oi.Id,odi.Amount...
坑
字符串变量为null的问题 
定义变量后declare @str nvarchar(10) 不赋值则是null 如果再有字符串相关的拼接操作 则结果很有可能都为null
所以需要设置set @str=''
知识点
函数DatePart 返回日期/时间单独部分 DATEPART(datepart,date)
年	yy, yyyy 
季度	qq, q
月	mm, m
年中的日	dy, y
日	dd, d
周	wk, ww
星期	dw, w
小时	hh
分钟	mi, n
秒	ss, s
毫秒	ms
微妙	mcs
纳秒	ns
问题
查询处理器用尽了内部资源,无法生成查询计划
在项目中动态拼接sql语句,使用union all连接结果集,每个查询语句都使用了in(几百个数值)
SELECT AA FROM T1 WHERE aa IN(1,2,3,4..............................)
UNION ALL
SELECT AA FROM T2 WHERE aa IN(1,2,3,4..............................)
主要是因为IN中数据量太大了 解决方案:使用临时表把in语句改成EXISTS语句
知识点
嵌套的事务
1.如果出现rollback tran 之类的是回滚所有 并不区分是内层还是外层 后面语句如果再有commit或rollback 会报错:‘COMMIT TRANSACTION 请求没有对应的 BEGIN TRANSACTION’ 所以内层rollback 往往跟return
2.如果没有save tran innerTran 想回滚内层 rollback tran innerTran 是报错的
3.内层save tran innerTran1 或save tran innerTran2 可以使用rollback tran innerTran1(回到这个状态)
4.只要外层rollback tran 内层不管什么状态都是回滚
知识点
select * from 多个表的写法
from 多个表后没有添加任何的关联条件 其实就是笛卡尔积 应避免该种写法 如果遇到 大多是错误的写法
知识点
Merge 语句的使用
根据与源表联接的结果,对目标表运行插入、更新或删除操作。 语法如下:
[ WITH  [,...n] ]  
MERGE
    [ TOP ( expression ) [ PERCENT ] ]
    [ INTO ]  [ WITH (  ) ] [ [ AS ] table_alias ]  
    USING  [ [ AS ] table_alias ]
    ON   
    [ WHEN MATCHED [ AND  ]  
        THEN  ] [ ...n ]  
    [ WHEN NOT MATCHED [ BY TARGET ] [ AND  ]  
        THEN  ]  
    [ WHEN NOT MATCHED BY SOURCE [ AND  ]  
        THEN  ] [ ...n ]  
    [  ]  
    [ OPTION (  [ ,...n ] ) ]
;  
其中 using 后的源 可以是多个表的关联;注意最后需要有分号
::=  
    { UPDATE SET  | DELETE }  
::=  
{  
    INSERT [ ( column_list ) ]
        { VALUES ( values_list )  
        | DEFAULT VALUES }  
}   
注意:无论哪种操作,都只能操作目标表;当为NOT MATCHED BY SOURCE 状态时,不能使用源表中的数据,即不能更新为源表中某个字段的内容,但可以指定一个常量
举个例子
   merge TestB T
   using TestC S
   on T.entryid=s.entryid  
   when matched
   then update set T.Des=S.Des
   when not matched
   then insert values(S.entryid,S.Des)
   when not matched by source
	   then delete
	   ;
知识点
Stuff 函数
它从第一个字符串的开始位置删除指定长度的字符;然后将第二个字符串插入到第一个字符串的开始位置。
语法:STUFF(character_expression , start , length , replaceWith_expression)
start 参数:
一个整数值(从1开始),指定删除和插入的开始位置。start 的类型可以是 bigint。
SELECT STUFF('abc',2,1,'EFG')
结果:aEFGc
知识点
For XML Path
该方式其实是用xml节点名称包装记录,展示为一条数据
默认情况下,最外层节点为Row,内层节点则是列的名称,举个例子:
SELECT T1 FROM TABLE For XML Path 的结果为:
1
2
也可以用For XML Path('') 不要最外层的row节点
当选择的列有计算时,如数字的加减,字符串的拼接,则该列被当作新列,没有名称!所以For XML Path 的用途一般为高效拼接字符串,举个例子:
 SELECT STUFF((SELECT ','+T1 From TABLE For XML Path('')),1,1,'') 
该语句的作用为用逗号分隔T1列中拼接的内容
知识点
表中一列字符串累加的处理
e.g 从表T中选择Name列,Name列有三行值为a,b,c
  declare @str nvarchar(1000) SET @str=''
  select  @str= @str+ CONVERT(nvarchar(50), ISNULL(Name,' ')) +','  from T
  select @str
结果:a,b,c,
该方法与For XML Path的结果基本相同,但没有它高效
知识点
变量处理列内容累加
比如,用分号分隔一列内容累加
declare @str nvarchar(1000) 
  select  @str= CONVERT(nvarchar, ISNULL(@str,''))+CONVERT(nvarchar, ISNULL(column,' ')) +';' 
  from table
  select @str
注意 1.需要定义变量存放值
2.不能从table中选择多列,否则语法有错误
知识点
必须指定别名的情况 
select t.* from(select 1 as t1) t
这种选择常量的,内层必须指定别名 否则会报:没有为 't' 的列 1 指定任何列名称
知识点
优化经验 
1.先弄懂业务 以及表之间的关系 确保各条件分支业务逻辑正确
2.通过查看预读,逻辑读,物理读次数找到耗时点
3.对于临时表 可以建立索引加快查询 (优化近20s)
4.查看执行计划 找出消耗占比大的步骤
5.发现其中有个Row Count Spool 占比较大 经过查阅资料 发现是与统计相关字段未建立索引 建立索引后优化27s左右
6.发现有复杂的更新子查询 但是不同更新数据又有上下父子级联动数据影响 检查后当前业务逻辑正确所以优化结束 增加参数过滤数据
7.对比 优化前1m多  优化后10s多
知识点
ROW_NUMBER()用法 
语法: ROW_NUMBER() OVER ( [ PARTITION BY value_expression , ... [ n ] ] order_by_clause ) 
使用方式一:
select t.* from(
   select ROW_NUMBER() over(order by id desc) as rownum,*  
   from TestA
   ) t
   where rownum between 2 and 3 order by T4
使用方式二:
;with orderSection as
(
    select ROW_NUMBER() OVER(order by id desc) rownum,* from TestA
)
select * from [orderSection] where rownum between 2 and 3
获取rownumber中排序的顺序 和主sql中的顺序应该一致 否则rownumber可能会不连续 感觉也没有不一致的场景。
增加PARTITION BY 的用法
若是在 T5 列上添加 PARTITION BY 子句,按照order by的顺序当 T5 值发生更改时将重新开始编号。 其实也是先按照T5排序,然后再按照T1排序
select ROW_NUMBER() over(partition by T5 order by T1 desc) as rownum,ID,T1,T5 from TestA
知识点
Rank()用法 
语法: RANK() OVER ( [ partition_by_clause ] order_by_clause )   
rank函数用于返回结果集的分区内每行的排名, 行的排名是相关行之前的排名数加一。简单来说rank函数就是对查询出来的记录进行排名,与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,如果使用rank函数来生成序号,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个,也就是相关行之前的排名数加一,可以理解为根据当前的记录数生成序号,后面的记录依此类推。
如 1,1,3,3,3,6
知识点
DENSE_RANK()用法 
语法: DENSE_RANK() OVER ( [ 
 ] < order_by_clause > )dense_rank函数的功能与rank函数类似,dense_rank函数在生成序号时是连续的,而rank函数生成的序号有可能不连续。dense_rank函数出现相同排名时,将不跳过相同排名号
如 1,1,2,2,2,3
知识点
NTILE()用法 
语法:NTILE (integer_expression) OVER ( [ 
 ] < order_by_clause > ) 参数 integer_expression:一个正整数表达式,用于指定每个分区必须被划分成的组数。 integer_expression 可以是 int 或 bigint 类型 。
关于该函数的说明:
如果分区的行数不能被 integer_expression 整除,则将导致一个成员有两种大小不同的组。 按照 OVER 子句指定的顺序,较大的组排在较小的组前面。 例如,如果总行数是 53,组数是 5,则前三个组每组包含 11 行,其余两个组每组包含 10 行。 另一方面,如果总行数可被组数整除,则行数将在组之间平均分布。 例如,如果总行数为 50,有五个组,则每组将包含 10 行。
select NTILE(2) over(order by T1 desc) as rownum,ID from TestA
分为两组 从1开始
 1,1,2,2 或 1,1,1,2,2
知识点
SELECT - Order by 子句 
语法:
ORDER BY order_by_expression  
    [ COLLATE collation_name ]   
    [ ASC | DESC ]   
    [ ,...n ]   
[  ]  
  
 ::=  
{   
    OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }  
    [  
      FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY  
    ]  
}  
举个例子
ORDER BY EntryOrder OFFSET 1 ROWS 
	FETCH NEXT 10 ROWS ONLY 
其中OFFSET后参数实际中可以为( @PageIndex * @PageSize ) - @PageSize 
NEXT后参数可以为	 @PageSize
知识点
链接服务器
添加链接服务器:exec sp_addlinkedserver '链接服务器名','','SQLOLEDB','服务器名或ip地址'
添加链接服务器登录方式:exec sp_addlinkedsrvlogin '链接服务器名','false',null,'数据库账号','密码'   
删除链接服务器:exec sp_dropserver '链接服务器名称', 'droplogins' 第一个参数是要删除的链接服务器;第二个参数作用是连带删除该链接服务器登录映射
--如果存在则删除
IF EXISTS (SELECT srvname FROM master.dbo.sysservers srv WHERE srvid != 0 AND srvname = N'RDMDSDB')
EXEC master.dbo.sp_dropserver @server=N'RDMDSDB', @droplogins='droplogins'
--增加链接服务器
EXEC sp_addlinkedserver
@server='RDMDSDB', --被访问的服务器别名
@srvproduct='sqlserver', --SqlServer默认不需要写
@provider=N'SQLNCLI', --不同的库都是不一样的,OLE DB字符
@datasrc='nrdmdsdb.h3c.com'--要访问的服务器
GO
--增加登录方式
EXEC sp_addlinkedsrvlogin 
@rmtsrvname='RDMDSDB', --被访问的服务器别名
@useself='false', --固定这么写
@locallogin=null, --本地操作应户名
@rmtuser='ISE_RDMDSNEW', --被访问的服务器用户名
@rmtpassword='NrdmdsDb4ISE43'--被访问的服务器用密码
GO
知识点
查看/操作 tempdb库
查看tempdb当前大小:exec sp_helpdb tempdb
对tempdb进行收缩:
use tempdb
go
dbcc shrinkfile(tempdev, 1024) --收缩文件
use tempdb
go
dbcc shrinkfile(templog, 512)--收缩日志
问题
不能创建大小为 9283 的行,该大小大于所允许的最大行大小 8060
每个表可以有1024列,表的行数及总大小仅受可用存储空间的限制,
每行最多可以存储8,060字节。
对于列过多导致行数据超过限定的情况,尽量不把数据放入表或临时表,直接取数或用CTE代替
知识点
统计某个字段中某个字符的个数
方法是把目标字符替换为空字符,再用原字符-替换后字符得到长度即可。
举个例子:统计“/”字符的个数
select len('888/6/35/1101')-len(replace('888/6/35/1101','/','')) from xxx
知识点
数据库作业用脚本展示 提升效率
原文链接:https://www.cnblogs.com/footleg/p/7131501.html
知识点
微软专家 一句话sql优化建议
1.in 中的值较多 建议反倒临时表中
2.select 中尽量不使用子查询
3.临时表 可以建索引
4.使用正向逻辑代替否定逻辑 e.g left join 替换 not in,  not exits
5.isnull 函数用不到索引 应使用col is null or  col=''
知识点
哪些情况需要建立索引
1.主键自动建立唯一索引
2.频繁作为查询条件的字段应该创建索引
3.查询中与其它表关联的字段,外键关联建立索引
4.频繁更新的字段不适合建索引(每次更新不单单是更新了记录还会更新索引)
5.where条件中用不到的字段不建索引
6.单键/组合索引(在高并发下建议建组合索引)
7.查询中排序的字段,排序字段通过索引去访问提高排序速度
8.查询中统计或分组字段
原文链接:https://blog.csdn.net/a332056918/article/details/81916255
知识点
子查询
子查询结果返回一个值(单行单列) 可以使用的运算符:><>=<==<>
select * from TestA
where T1 > ( select T1 from TestA where ID=2) ;
子查询结果返回多行(多行单列) 可以使用运算符:>ALL >ANY <ALL <ANY in
select * from TestA
where T1>All(select T1 from TestA where ID=2)
select * from TestA
where T1>Any(select T1 from TestA where ID=2)
子查询结果返回多行多列 在sqlserver中 需要使用运算符checksum辅助 oracle或Mysql中直接用(ColumnA,ColumnB)就可以
select * from TestA
where checksum(T1,T2) in 
 ( 
   select checksum(T1,max(T2))
   from TestA
   group by T1 
 )
也可以用Exists 关键字 内外关联字段处理
关联子查询:关联子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。所以关联子查询,先执行主查询,再执行子查询
非关联子查询:是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。所以非关联子查询,先执行子查询,再执行主查询
坑
表中的字段最长为128 如果超出则会报错
实际中的报错:
消息 103,级别 15,状态 4,第 194 行
以 '1_solPart_15_LS-5130S-28S-EI;LS-5130S-28P-EI;LS-5130S-28P-HPWR-EI;LS-5130S-10P-HPWR-EI;S5110V2-28P-HPWR;5110V2-52P-PWR;S5120V2-2' 开头的 标识符 太长。最大长度为 128。
在有类似行转列操作时,部分数据由用户自己输入容易引发该问题。
最后解决办法是不使用名称而改用id作为列名,取出数据后到程序中再根据id找到名称。
知识点
使用try catch 以及相关报错信息
使用try catch的结构如下:
BEGIN TRY
	需要捕捉异常的程序块
END TRY
BEGIN CATCH
	异常处理块
END CATCH
ERROR_NUMBER() --返回错误代码
ERROR_SEVERITY() --返回错误的严重级别
ERROR_STATE() --返回错误的状态码
ERROR_MESSAGE() --返回错误的完整信息
知识点
数据随机排序 或 随机取数
这里主要用到了NewID() 函数,把它放在Order By 后即可:
SELECT * FROM TableA ORDER BY NEWID()
报错
已超过了锁请求超时时段  1222
现象:
1.执行truncate语句 一直得不到结果(应该很快完成才对)
2.所有表都刷新不出来
定位问题:
那么只有一种可能就是该TRUNCATE语句位于事务里面,而该事务由于逻辑原因等一直没有提交或回滚。
参考:https://www.cnblogs.com/kerrycode/p/4502164.html
错误一则
Insert语句与Foreign Key约束冲突
问题分析:
1.一般出现在表中建了外键的情况
2.该问题是在外键表中插入了不存在的主表的主键值
举例:
Create Table TestA
(
ID int primary key
)
Create Tabel TestB
(
ID int primary key,
WID int
)
Constraint FK_TestB_TestA(ID) References TestA
执行如下语句:
Insert Into TestB
Select 1,999
会报INSERT 语句与FOREIGN KEY约束FK_TestB_TestA冲突,该冲突发生在数据库XXXX,表dbo.TestA,Column 'ID'。语句已终止
知识点
设置自增表种子值
USE AdventureWorks2012;
GO
DBCC CHECKIDENT ('Person.AddressType', RESEED, 10);
GO
知识点
查询数据库中表,视图,存储过程,函数,触发器,用户定义类型的信息
所有表信息
SELECT name,create_date,modify_date
FROM sys.objects
WHERE type = 'U'
order by name
所有触发器
SELECT name AS 'Trigger Name', OBJECT_NAME(parent_id) AS 'Table Name',create_date,modify_date
FROM sys.triggers;
所有视图信息
SELECT name,create_date,modify_date
    FROM sys.objects
    WHERE type = 'V'
    order by name
所有存储过程信息
SELECT name,create_date,modify_date
    FROM sys.objects
    WHERE type = 'P'
    order by name
所有标量值函数
SELECT name,create_date,modify_date
    FROM sys.objects
    WHERE type = 'FN' AND is_ms_shipped = 0
    order by name
所有表值函数
SELECT name,create_date,modify_date
    FROM sys.objects WHERE type = 'TF' 
    UNION
    SELECT name,create_date,modify_date
    FROM sys.objects WHERE type = 'IF' 
    order by name
所有用户定义表类型
SELECT name 
    FROM sys.table_types 
    WHERE is_user_defined = 1
知识点
查询一个对象是什么类型
SELECT OBJECT_NAME(object_id) AS ObjectName,
       CASE WHEN type = 'U' THEN 'Table'
            WHEN type = 'V' THEN 'View'
            WHEN type = 'P' THEN 'Stored Procedure'
            ELSE ''
       END AS ObjectType
	FROM sys.objects
	WHERE name IN ('对象名');
知识点
日期处理相关函数
YEAR() 函数:返回日期的年份
Year('2024-1-1') 结果:2024
MONTH() 函数:返回日期的月份。
Year('2024-1-1') 结果:1
DATEDIFF(interval,startdate,enddate) 函数:计算两个日期之间的差异。其中interval可以是年y,季度q,月m,日d,周w,小时h,分钟mi,秒s
DATEDIFF(DAY,'2024-1-1','2024-1-5') 结果:4